/*
 * chrome://tabmixplus/content/links/userInterface.js
 *
 * original code by Bradley Chapman
 * modified and developped by Hemiola SUN
 * modified again by Bradley Chapman
 *
 */
var gIOService =     Components.classes["@mozilla.org/network/io-service;1"]
                     .getService(Components.interfaces.nsIIOService);
var gPref =          Components.classes["@mozilla.org/preferences-service;1"]
                     .getService(Components.interfaces.nsIPrefBranch);
var gURIFixer =      Components.classes["@mozilla.org/docshell/urifixup;1"]
           .getService(Components.interfaces.nsIURIFixup);
var gWindowManager = Components.classes["@mozilla.org/appshell/window-mediator;1"]
           .getService(Components.interfaces.nsIWindowMediator);

/**
 * @brief Catch call to tabmix options from EM
 *        we only use Tabmix options if we have browser window
 *
 * @param aURL       A valid options URL string.
 *
 * @return           true if the URL is for tabmix options
 *                   false if not.
 *
 */
function TMP_cmd_options(aURL)
{
   if (aURL != "chrome://tabmixplus/content/pref/pref-tabmix.xul")
      return false;

   var anyWindow = gWindowManager.getMostRecentWindow("navigator:browser");

   if (!anyWindow) {
      var tabmixopt = gWindowManager.getMostRecentWindow("mozilla:tabmixopt");
      if (tabmixopt)
         tabmixopt.close();

      var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
                                    .getService(Components.interfaces.nsIPromptService);
      var stringBundle = document.getElementById("tmp-string-bundle");
      var title = stringBundle.getString("tabmixoption.error.title");
      var msg = stringBundle.getString("tabmixoption.error.msg");
      promptService.alert(window, title, msg);
   }
   else
      anyWindow.TMP_openDialog(-1);

   return true;
}

/**
 * @brief Load URLs from the Extension/Theme Managers, and item with text-link class
 *
 * This redefines chrome://mozapps/content/extensions/extensions.js:openURL()
 *
 * @param aURL       A valid URI string.
 * @param event      A valid event union. This can be null when
 *                   calling this function.
 * @return           true.
 *
 */
function TMP_openURL(aURL, event)
{
   var linkTarget, loadInBackground;
   try {
            linkTarget = gPref.getIntPref("browser.link.open_newwindow");
   }
   catch (e) {
      linkTarget = 1;
   }

   if (aURL == null) aURL = "about:blank";

   // check for an existing window and focus it; it's not application modal
   var anyWindow = gWindowManager.getMostRecentWindow("navigator:browser");

   if (!anyWindow) {
      openDialog("chrome://browser/content/browser.xul", "_blank", "chrome,all,dialog=no", aURL, null, null, null);
      if (event && event instanceof Event) {
         event.preventDefault();
         event.stopPropagation();
      }
      return true;
   }

   var anyBrowser = anyWindow.getBrowser();
   var originCharset = anyBrowser.contentDocument.characterSet;

   // if the current tab is empty, then do not open a new tab
   if (anyBrowser.selectedBrowser.webNavigation.currentURI.spec == "about:blank") {
      // 1: CURRENT_TAB
      linkTarget = 1;
      originCharset = null;
   }

      switch (linkTarget) {
         case 1 :
            anyBrowser.loadURI(aURL, null, originCharset);
            break;
         case 2 :
            var f = anyWindow.openNewWindowWith.toString();
            if (f.indexOf("securityCheck") == -1)
               anyWindow.openNewWindowWith(aURL, null, null, false); // firefox 1.5 +
            else
               anyWindow.openNewWindowWith(aURL, null, true, null); // firefox 1.0.x
            break;
         case 3 :
            // added by request, for extensions with multiple homepages
            var urls = aURL.split("|");
            var firstTab = anyBrowser.addTab(urls[0], null, originCharset);
            // only select the EM/TM link when asked to do so
            anyBrowser.TMP_selectNewForegroundTab(firstTab);
            for (var i = 1; i < urls.length; ++i) {
               anyBrowser.addTab(urls[i], null, originCharset);
            }
            anyBrowser.mTabContainer.nextTab = 1;
            break;
      }

   if (event && event instanceof Event) {
      event.preventDefault();
      event.stopPropagation();
   }
   return true;
}

function TMP_BrowserOpenTab(aTab)
{
   var newTabContent = TMP_getIntPref(tabxBranch, "loadOnNewTab", 0 );
   var loadInBackground = TMP_getBoolPref(tabxBranch, "loadNewInBackground", true );

   var url;
   switch (newTabContent) {
      case 0 : // blank tab, by default
         url = "about:blank";
         break;
      case 1 :  // home page
         url = gHomeButton.getHomePage().split("|")[0];
         break;
      case 2 : // current URI
         var currentURI = gBrowser.selectedBrowser.webNavigation.currentURI;
         url = currentURI ? currentURI.spec : "about:blank";
         break;
      case 3 : // duplicate tab
         gBrowser.duplicateTab(gBrowser.selectedTab);
         return;
      case 4 : // user url
         try {
            url = gPref.getComplexValue("extensions.tabmix.newTabUrl",
                                Components.interfaces.nsIPrefLocalizedString).data;
         } catch (e) {   }
         // use this if we can't find the pref
         if (!url)
            url = "about:blank";
         break;
   }
   var originCharset = url != "about:blank" ? gBrowser.selectedBrowser.contentDocument.characterSet : null;
   var newTab = gBrowser.addTab(url, null, originCharset);

   if (aTab && aTab.localName == "tab") {
      var pos = newTab._tPos > aTab._tPos ? 1 : 0;
      gBrowser.TMmoveTabTo(newTab, aTab._tPos + pos);
   }
   content.focus();
   gBrowser.TMP_selectNewForegroundTab(newTab, loadInBackground, url);
}

/**
 * @brief Load URLs generated by the search bar and the search dialog.
 *
 * @param aData            A string containing aData from new service, FF 2.0,
                           or a URI for older FF versions.
 * @param theSecondArg     a valid event union: FF 1.0.7 and FF 1.5+ (see eval in tablib) - called from searchbar
                           or a Boolean value - call from searchDialog.
 * @param newService       A Boolean value, if true we are in FF 2.0 + (after 2006-03-17)
 * @return                 Nothing.
 *
 */

// XXX need to fix TMP_SearchLoadURL to work like in Fx 3.0
// #351253 [Firefox:Search]-Search button misinterprets modifiers when clicked [All]
function TMP_SearchLoadURL(aData, theSecondArg, newService)
{
  var theTabPref = TMP_getBoolPref(tabxBranch, "opentabfor.search", false)
  var theBGPref  = TMP_getBoolPref(tabxBranch, "loadSearchInBackground", false)

  var URI, postData = null;
  if (typeof(newService) == "boolean" && newService) {
     // Bug 336925: Middle clicking search button should open new tab search.xml version 1.67
     // Always open in a new tab on a middle-click; otherwise examine the
     // preference and the alt key.
     if (theSecondArg && "button" in theSecondArg && theSecondArg.button == 1)
        theTabPref = true;

     var searchbar = document.getElementById("searchbar");
     var submission = searchbar.currentEngine.getSubmission(aData, null);
     URI = submission.uri.spec;
     postData = submission.postData;
  }
  else
     URI = aData;

  __TMP_LoadBarURL(URI, theSecondArg, theTabPref, theBGPref, postData, false);
  return;
}

/**
 * @brief Load URLs from the URL bar.
 *
 * @param event         A valid event union.
 * @param aPostData     Additional opaque data used by __TM_LoadBarURL().
 * @return              Nothing.
 *
 */
function TMP_BrowserLoadURL(theEvent, aPostData)
{
  var theTabPref = TMP_getBoolPref(tabxBranch, "opentabfor.urlbar", false)
  var theBGPref  = TMP_getBoolPref(tabxBranch, "loadUrlInBackground", false)

  var theURI = document.getElementById("urlbar").value;
  __TMP_LoadBarURL(theURI, theEvent, theTabPref, theBGPref, aPostData, true);
}

/**
 * @brief Load URLs from the URL bar, search bar and search dialog.
 *
 * This function is used directly by Tab Mix Plus.
 *
 * @param theURI        The URI to be opened.
 * @param theEvent      A valid event union, or a Boolean value when
 *                      called by TMP_SearchLoadURL().
 * @param theTabPref    A Boolean preference - if true, the URL will be
 *                      opened in a new tab; if false, it will load in
 *                      the current tab.
 * @param theBGPref     A Boolean preference - if false, the newly created tab will be focused;
 *                      if true, the newly created tab will be unfocused.
 * @param thePostData   Additional opaque data used by tabbrowser methods
 * @param aAllowThirdPartyFixup   Allow third-party services to fixup this URL
 * @returns             Nothing.
 *
 */
function __TMP_LoadBarURL(theURI, theEvent, theTabPref, theBGPref, thePostData, aAllowThirdPartyFixup)
{
  var newTab, origTab, originCharset = null, isBlankTab, isAltKey = false;

  if (gBrowser.localName != "tabbrowser") {
    // _content is deprecated somewhere
    loadURI(theURI, null, thePostData, aAllowThirdPartyFixup);
    _content.focus();
    return;
  }
  else {
    var currentURI = gBrowser.selectedBrowser.webNavigation.currentURI;
    var url = currentURI ? currentURI.spec : "about:blank";
    originCharset = url != "about:blank" ? gBrowser.selectedBrowser.contentDocument.characterSet : null;
  }

  // if we are viewing source, then do so
  if (gIsOldBrowser && theURI.match(/^view-source:/)) {
    handleURLBarRevert();
    BrowserViewSourceOfURL(theURI.replace(/^view-source:/, ""), null, null);
    return;
  }

  // open link in new tab, either because theTabPref is true or because
  // the user used the Alt key on the URL bar
  isAltKey = (theEvent instanceof Event && ('altKey' in theEvent && theEvent.altKey));
  if (TMP_whereToOpen(theTabPref, isAltKey).inNew) {
      // FIXED: restore the URL bar
      origTab = gBrowser.selectedTab;
      TMP_handleURLBarRevert(origTab);
      // FIXED: don't send the referrer, this may be a security hole and
      // clutters server logs; thanks go to jruderman
      try {
        var lastBrowser = gBrowser.mPanelContainer.lastChild.firstChild;
        newTab = gBrowser.addTab(theURI, null, originCharset, thePostData, null, aAllowThirdPartyFixup);
      } catch (e) {
         // remove the new tab if after the new tab was opened the url failed to load
         var newLastBrowser = gBrowser.mPanelContainer.lastChild.firstChild;
         if (newLastBrowser != lastBrowser) {
            newTab = gBrowser.getTabForBrowser(newLastBrowser);
            gBrowser.removeTab(newTab);
         }
         return;
      }
      gBrowser.TMP_selectNewForegroundTab(newTab, theBGPref);
      // in Firefox 1.5, markLinkVisited() has been removed
      if (theEvent instanceof Event && "markLinkVisited" in window)
         TMP_markLinkVisited(theURI, theEvent.target);
  }
  // not opening in a new tab at all
  else
    loadURI(theURI, null, thePostData, aAllowThirdPartyFixup);

  // _content is deprecated somewhere
  _content.focus();

  if (theEvent instanceof Event) {
    theEvent.preventDefault();
    theEvent.stopPropagation();
  }
  return;
}

/**
 * @brief Revert the URL bar to the URL of the currently selected browser.
 *
 * This was borrowed from chrome/browser.jar!/content/browser/browser.js:1840
 *
 * If "ESC" is pressed in the url bar, we replace the urlbar's value
 * with the url of the page, unless it is about:blank, where we reset
 * it to "".
 *
 * @returns       true if the URL bar dropdown is open,
 *                false if not.
 *
 */
function TMP_handleURLBarRevert(browserTab)
{
  var url;
  if (browserTab == null) {
    url = getWebNavigation().currentURI.spec;
  }
  else {
    // use the browserTab's currentURI instead
    url = gBrowser.getBrowserForTab(browserTab).webNavigation.currentURI.spec;
  }

  var throbberElement = document.getElementById("navigator-throbber");
  var isScrolling = gURLBar.popupOpen;

  // don't revert to last valid url unless page is NOT loading
  // and user is NOT key-scrolling through autocomplete list
  if ((!throbberElement ||
       !throbberElement.hasAttribute("busy")) && !isScrolling) {
    if (url != "about:blank" || content.opener) {
      gURLBar.value = url;
      SetPageProxyState("valid");
    }
    else { //if about:blank, urlbar becomes ""
      gURLBar.value = "";
      SetPageProxyState("invalid");
    }
  }

  gBrowser.userTypedValue = null;

  // tell widget to revert to last typed text only if the user
  // was scrolling when they hit escape
  return !isScrolling;
}

/**
 * @brief Perform URI fixup on potentially broken URLs before
 * passing them to markLinkVisited.
 *
 * NOTE:
 * in Firefox 1.5, markLinkVisited() has been removed and
 * superseded by core history code that takes care of marking
 * links visited.
 *
 * @param url        A URL string.
 * @param linkNode   A DOM node that contains the URL string.
 * @returns          Nothing.
 *
 */
function TMP_markLinkVisited(url, linkNode)
{
   var visitedURI = gURIFixer.createFixupURI(url, 0);
//   if (self.markLinkVisited && visitedURI && linkNode) {
   if (visitedURI && linkNode) {
     markLinkVisited(visitedURI.spec, linkNode);
   }
   return;
}

// openUILink handles clicks on UI elements that cause URLs to load.
function TMP_openUILink( url, e, ignoreButton, ignoreAlt, allowKeywordFixup, postData, referrerUrl)
{
  var where = whereToOpenLink(e, ignoreButton, ignoreAlt);

  // don't open blanke tab when we are about to add new livemark
  var _addLivemark = "FeedHandler" in window && /^feed:/.test(url) && 
                     gPref.getCharPref("browser.feeds.handler") == "bookmarks";

  if (where == "current" && TMP_openUILink.caller.name != "openTopWin")
    where = TMP_checkCurrent(url);

  try {
    var lastBrowser = gBrowser.mPanelContainer.lastChild.firstChild;
    openUILinkIn(url, where, allowKeywordFixup, postData, referrerUrl);
  } catch (ex) {
    // remove the new tab if after the new tab was opened the url failed to load
    var newLastBrowser = gBrowser.mPanelContainer.lastChild.firstChild;
    if (where == "tab" && newLastBrowser != lastBrowser) {
      var newTab = gBrowser.getTabForBrowser(newLastBrowser);
      gBrowser.removeTab(newTab);
    }
  }
}

function TMP_checkCurrent(url)
{
  var browser = getTopWin().document.getElementById("content");
  if (browser.mCurrentTab.hasAttribute("locked")) {
    var isBlankTab = browser.isBlankNotBusyTab(browser.mCurrentTab);
    if (!isBlankTab)
       return "tab";
  }
  else if (gPref.getIntPref("extensions.tabmix.speLink") == 2 ) {
    // Get current page url
    var curpage = browser.mCurrentBrowser.webNavigation.currentURI.spec;
    var domain = checkDomain(curpage, url);
    if (domain.current && domain.target && domain.target != domain.current)
      return "tab";
  }
  return "current";
}
